﻿using System;
using System.Data;

namespace BizElements.BusinessLayer
{
    /// <summary>
    /// A method which can modify the fetched data.
    /// </summary>
    /// <param name="data">Original data fetched form the data-source.</param>
    /// <returns>Modified data.</returns>
    /// <remarks>This can be used to add a computed column in the fetched DataTable, or reformat fetched data etc.</remarks>
    [Serializable]
    public delegate DataView PostProcessDelegate(DataView data);

    /// <summary>
    /// Generic search engine which accesses the data-source and provides meta-data for all search elements.
    /// </summary>
    public interface ISearchEngine
    {
        #region Methods.

        /// <summary>
        /// Adds user defined sort expression for the retrieved values.
        /// </summary>
        /// <param name="field">Field by whitch the the results are ordered.</param>
        /// <param name="ascending">Specifies whether the values in the specified fields should be sorted in 
        /// ascending order, from lowest value to highest value.</param>
        void AddSortExpression(string field, bool ascending);

        /// <summary>
        /// Clears user-defined sort expressions.
        /// </summary>
        void ClearSortExpressions();

        /// <summary>
        /// Gets user defined sort expressions for the retrieved values.
        /// </summary>
        /// <returns>Array of sort expressions.</returns>
        SearchEngineSortExpression[] GetSortExpressions();

        /// <summary>
        /// Fetches data which matches the given key values.
        /// </summary>
        /// <param name="pkValues">Key values given in the order as specified in the <see cref="PrimaryKeyFields"/> property.</param>
        /// <returns>Data which matched the given criteria.</returns>
        DataView FetchByPkValues(object[,] pkValues);

        /// <summary>
        /// Creates a dynamic filter and retrieves data. Calls PostProcess delegate if provided when it's done.
        /// </summary>
        /// <returns>Data that matches the user defined criteria.</returns>
        DataView Search();

        /// <summary>
        /// Creates a dynamic filter and counts all records in the data-source that match the filter criteria.
        /// </summary>
        /// <returns>Total number of records that match the criteria.</returns>
        /// <remarks>Usefull when the number of records retrieved by <see cref="Search"/> method has been limited
        /// by <see cref="MaxNumberOfRecordsReturned"/> property.</remarks>
        int Count();

        #endregion

        #region Properties.

        /// <summary>
        /// FieldPermissions which are to be retrieved and displayed in the search results.
        /// </summary>
        IBindableFieldCollection DisplayFields { get; }

        /// <summary>
        /// Maximum numbers of records to retrieve from the data-source.
        /// </summary>
        int MaxNumberOfRecordsReturned { get; set; }

        /// <summary>
        /// A method which can modify the fetched data.
        /// </summary>
        /// <remarks>This can be used to add a computed column in the fetched DataTable, or reformat fetched data.</remarks>
        PostProcessDelegate PostProcess { set; }

        /// <summary>
        /// Primary key fields which uniquely identify a data-source record.
        /// </summary>
        IBindableFieldCollection PrimaryKeyFields { get; }

        /// <summary>
        /// FieldPermissions whose begin and end values users can change to create a dynamic filter.
        /// </summary>
        ISearchEngineFieldCollection SearchFields { get; }

        /// <summary>
        /// Specifies whether sorting will take place on the data-source or in engine after the data has been fetched.
        /// </summary>
        bool SortOnDb { get; set; }

        #endregion

        #region Events.

        /// <summary>An event that occurs immediately after the data are fetched but before the <see cref="PostProcess"/> delegate is called.</summary>
        event EventHandler<EventArgs<DataView>> DataFetched;

        /// <summary>An event that occurs after <see cref="PostProcess"/> delegate, i.e. just before the engine returns the data to client.</summary>
        event EventHandler<EventArgs<DataView>> DataReady;

        #endregion
    }
}